﻿using MongoDB.Bson.Serialization.Attributes;
using System;

namespace Sustainalytics.ESG.Entities
{
    [BsonIgnoreExtraElements]
    public class RPPerformance
    {
        private const double Epsilon = 1e-16;

        public RPPerformance()
        {
            Assessment = new RPAssessment();
        }

        public RPAssessment Assessment { get; set; }
        public DateTime? AssessmentTimestamp { get; set; }

        public Timestamped<double> Score { get; set; }
        public Timestamped<int?> Rank { get; set; }
        public Timestamped<int> GroupCount { get; set; }
        public TimestampedFloat Percentile { get; set; }
        public TimestampedFloat Weight { get; set; }
        public TimestampedFloat Min { get; set; }
        public TimestampedFloat Avg { get; set; }
        public TimestampedFloat Max { get; set; }

        public MomentumDataPoint ScoreMomentumYoY { get; set; }
        public MomentumDataPoint ScoreMomentumMoM { get; set; }
        public MomentumDataPoint PercentileMomentumYoY { get; set; }
        public MomentumDataPoint PercentileMomentumMoM { get; set; }

        private MomentumDataPoint GetMomentumScore(double? previousScore, DateTime date)
        {
            if (!previousScore.HasValue)
                return null;

            if (previousScore.Value <= Epsilon)
            {
                return new MomentumDataPoint
                {
                    DataPoint = 0,
                    Date = date,
                    Value = previousScore.GetValueOrDefault()
                };
            }

            return new MomentumDataPoint
            {
                DataPoint = (Score - previousScore.Value) * 100 / previousScore.Value,
                Date = date,
                Value = previousScore.GetValueOrDefault()
            };
        }

        public void SetYoYMomentumScore(double? previousScore, DateTime date)
        {
            ScoreMomentumYoY = GetMomentumScore(previousScore, date);
        }

        public void SetMoMMomentumScore(double? previousScore, DateTime date)
        {
            ScoreMomentumMoM = GetMomentumScore(previousScore, date);
        }

        private MomentumDataPoint GetMomentumPercentile(double? previousPercentile, DateTime date)
        {
            if (!previousPercentile.HasValue)
                return null;

            return new MomentumDataPoint
            {
                DataPoint = (Percentile - previousPercentile.Value),
                Date = date,
                Value = previousPercentile.GetValueOrDefault()
            };
        }

        public void SetYoYMomentumPercentile(double? previousPercentile, DateTime date)
        {
            PercentileMomentumYoY = GetMomentumPercentile(previousPercentile, date);
        }

        public void SetMoMMomentumPercentile(double? previousPercentile, DateTime date)
        {
            PercentileMomentumMoM = GetMomentumPercentile(previousPercentile, date);
        }
    }
}
